import tensorflow.compat.v1 as tf
import numpy as np

# 在tensorflow框架下编写python代码，创建一个简单的神经网络，并预测结果。
# (一)	导入tensorflow模块（8分）
# (二)	准备数据集（共12分，各6分）
x_data = [[0, 0, 1, 0, 1],
          [1, 1, 1, 1, 1],
          [1, 0, 1, 1, 0],
          [0, 1, 1, 0, 1]]
y_data = [[0],
          [1],
          [1],
          [0]]
x_data = np.array(x_data)
m, n = x_data.shape
y_data = np.array(y_data)
L1 = n * 2
L2 = y_data.shape[1]

# (三)	定义变量X（8分）和Y（8分）
x = tf.placeholder(tf.float32, [None, n], name='placeholder_x')
y = tf.placeholder(tf.float32, [None, 1], name='placeholder_y')

# (四)	定义预测值，可用sigmoid函数（8分）
w1 = tf.Variable(tf.random.normal([n, L1]), dtype=tf.float32, name='w1')
b1 = tf.Variable(tf.random.normal([1, L1]), dtype=tf.float32, name='b1')
w2 = tf.Variable(tf.random.normal([L1, L2]), dtype=tf.float32, name='w1')
b2 = tf.Variable(tf.random.normal([1, L2]), dtype=tf.float32, name='b1')
z1 = tf.matmul(x, w1) + b1
a1 = tf.nn.sigmoid(z1)
z2 = tf.matmul(a1, w2) + b2
a2 = tf.nn.sigmoid(z2)
predict = tf.cast(a2 > 0.5, dtype=tf.float32)

# (五)	定义代价函数（8分）
cost = - tf.reduce_mean(y * tf.math.log(a2) + (1 - y) * tf.math.log(1 - a2))

# accuracy
acc = tf.reduce_mean(tf.cast(tf.equal(a2 > 0.5, y > 0.5), dtype=tf.float32))

# (六)	使用梯度下降优化器（8分）
alpha = 0.1
train = tf.train.GradientDescentOptimizer(learning_rate=alpha)\
    .minimize(cost)

# (七)	创建会话（8分）
with tf.Session() as sess:

    # (八)	全局变量初始化（8分）
    sess.run(tf.global_variables_initializer())

    # (九)	迭代3001次，每300次输出一次代价值（8分）
    iters = 3001
    group = 300
    for i in range(iters):
        _, costv, accv = sess.run([train, cost, acc],
                                  feed_dict={x: x_data, y: y_data})
        if i % 300 == 0:
            print(f'#{i + 1}, cost = {costv}, acc = {accv}')

    # (十)	对数据[1,0,0,0,1]进行预测，输出结果。（8分）
    proba, h = sess.run([a2, predict], feed_dict={x: [
        [1, 0, 0, 0, 1]
    ]})
    print(f'对数据[1,0,0,0,1]进行预测: {h} ({proba})')

    # (十一)	对数据[1,1,1,1,1]进行预测，输出结果。（8分）
    proba, h = sess.run([a2, predict], feed_dict={x: [
        [1,1,1,1,1]
    ]})
    print(f'对数据[1,1,1,1,1]进行预测: {h} ({proba})')
